<template>
  <div>
    <!--输入框。输入的值通过调用el-tree的隐式.filter(value)方法实现筛选功能-->
    <el-input placeholder="输入关键字进行过滤" v-model="filterText"></el-input>
    <!--注意:filter-node-method绑定的方法，当调用el-tree隐函数.filter(value)时，指定绑定的过滤方法-->
    <!--绑定的方法解释见下方详细方法-->
    <el-tree
      :data="menus"
      :props="defaultProps"
      node-key="catId"
      ref="menuTree"
      @node-click="returnToFather"
      :filter-node-method="filterNode"
      :highlight-current="true"
    >
    </el-tree>
  </div>
</template>

<script>
//这里可以导入其他文件（比如组件、工具js、第三方插件js、json文件、图片文件等）
//例如：import 组件名称  from '组件路径';

export default {
  //import 引入的组件需要注入到对象中才可以使用
  name: "treeCategory",
  components: {},
  props: {},
  data() {
    // 这里存放数据
    return {
      // 这里menus会被映射到el-tree的data属性，menus中的数据应该从后端获取
      // 在新建这个vue时，完全可以令menus为空
      menus: [],
      // 过滤关键字
      filterText: "",
      // 这里defaultProps会被映射到el-tree的props属性
      defaultProps: {
        // 对应的后端接口返回的是 Entity类，这个变量中有一个（我们定义的，名字随便取的）存放其子菜单的变量——不知道是啥，根据这个组件被用到的地方决定
        // 而el-tree的属性参数（不能更改的）children用于声明子菜单变量名。因此这里就是  children: "children"
        children: "children",
        // 对应的后端接口返回的是 Entity类，这个变量中有一个（自动根据数据库生成的，与数据库字段同名）存放当前菜单名称的变量——不知道是啥，根据这个组件被用到的地方决定
        // 而el-tree的属性参数（不能更改的）label用于声明菜单名称变量名。因此这里就是  label: "name"
        label: "name",
      },
      // 默认展开的菜单
      expandedKey: [],
    };
  },
  //计算属性  类似于data 概念
  computed: {},
  //监控data中的数据变化
  watch: {
    // 监控全局变量filterText的值的变化
    // 一旦filterText的值发生了变化，立刻调用el-tree的隐函数.filter(value)并把新的值传递过去
    // 隐函数.filter(value)会调用el-tree中通过:filter-node-method绑定的过滤方法
    filterText(val) {
      this.$refs.menuTree.filter(val);
    },
  },
  //方法集合
  methods: {
    // 根据过滤关键字对树节点进行过滤
    // 这个方法就是el-tree中:filter-node-method绑定的方法，被隐函数.filter(value)拉起。这个方法有三个el默认输入参数，必须实现的是前两个
    // 第一个输入参数是隐函数.filter(value)传递来的value，第二个参数是当前结点对应的entity(不是结点数据)
    // filterNode会对所有结点进行遍历执行，return值为1则显示该结点，否则不显示该结点
    filterNode(value, data) {
      if (!value) return true;
      return data.name.indexOf(value) !== -1;
    },
    // 在注入对象的methods中编写一个方法从后端获取数据，用于刷新页面
    getMenus() {
      // this.$http代表当前对象访问的http属性，关于这个方法的详细信息可以去看src/utils/httpRequest.js
      // this.http(括号内书写http属性，如果有多个属性，则使用{大括号括起来})
      this.$http({
        // 属性url:this.$http.adornUrl("编写后端Controller接口的全路径")——是啥不知道，根据这个组件被用在哪里决定
        // 前端会向  $http.adornUrl/括号内容  发起请求。$http.adornUrl是前端项目的默认路径，一般我们设置为网关路径，具体在index.js中配置
        url: this.$http.adornUrl("/gulimallproduct/category/list/tree"),
        // 属性method: "声明访问后端接口是get还是post，当然这里和Controller保持一致"
        method: "get",
        /*
        // 属性params:this.$http.adornParams书写访问后端地址时的参数信息，如果是get方法，他们会以   ?$参数名=xxx   的形式附加在请求地址后面
        // params:this.$http.adornParams(括号内书写访问附加参数，如果多个参数，使用{大括号括起来})
        // 在本例中因为没有访问参数，所以下面的内容先注释掉
        params: this.$http.adornParams({
          // 用 page: this.pageIndex:  声明访问参数
          // page就是会附加在访问地址？后的内容
          // 如果之前在  data(){中集合了数据}，  则这里就要使用   this.data中数据的名称   来获取，否则直接给值就行
          page: this.pageIndex,
        }),
        */
        //  访问成功以后要做什么？
        //  注意，这里的data只能使用data！！！！不能使用  this.data
        //  因为vscode规定，后端返回的json文件以data命名，所以这里的{data}是在接收json数据
        //  如果我们在控制台查看，我们发现这个名为data的json数据包中，存放了我们当初在Controller中定义返回值时，放入的
        //  return R.ok().put("AAAA", BBBB);  这个键值对
        // 也就是说这个json包中，名为 AAAA 的键下，存放着所有的菜单信息。
        //  所以把这个AAAA拿出来就是了呗
        // AAAA——不知道是啥，根据这个组件被用在哪里决定
      }).then(({ data }) => {
        console.log("成功获取到菜单数据...", data.allcategory);
        this.menus = data.allcategory;
      });
    },

    // 作为子模块的点击方法，用来向父模块传递参数
    // 使用el-tree的三个参数作为输入参数：Entity、Node、自身组件名
    returnToFather(entity, node, component) {
      // 使用$emit向父模块传递一个事件，这个事件的名称就叫dataReturnToFather
      // 在父模块中可以使用@dataReturnToFather="处理方法"来接收这传递事件并进行处理。
      this.$emit("dataReturnToFather", entity, node, component);
    },
  },
  //生命周期---创建完成（可以访问当前this实例）
  //  一旦创建这个页面组件，就会执行created中的方法
  //  当然，这个方法是需要在注入对象的methods中完成定义的
  created() {
    this.getMenus();
  },
  //生命周期---挂载完成（可以访问DOM元素）
  mounted() {},
  beforeCreate() {}, // 生命周期---创建之前
  beforeMount() {}, // 生命周期---挂载之前
  beforeUpdate() {}, // 生命周期---更新之前
  updated() {}, // 生命周期---更新之后
  beforeDestroy() {}, // 生命周期---销毁之前
  destroyed() {}, // 生命周期---销毁完成
  activated() {}, // 如果页面有keep-alive 缓存功能，这个函数就会触发
};
</script>
<style  scoped>
</style>